package cn.virens.common.util.components.bytes;


import cn.virens.common.util.core.number.ByteUtil;
import cn.virens.common.util.exception.APIException;

import java.io.Serializable;
import java.util.Arrays;

@SuppressWarnings("serial")
public class BytesBuilder implements Serializable {
    private byte[] bytes;

    private int capacity;
    private int count;

    public BytesBuilder() {
        this(64);
    }

    public BytesBuilder(int capacity) {
        this.bytes = new byte[capacity];
        this.capacity = capacity;
        this.count = 0;
    }

    public BytesBuilder append(byte[] bs) throws APIException {
        if (bs == null || bs.length == 0) return this;

        // 扩容byte数组
        int len = bs.length;

        // 判断当前数组容量是否能够容纳新数据
        if (count + len > bytes.length) {
            this.bytes = dil(bytes, capacity, len);
        }

        // 将本次数据给存放进来
        System.arraycopy(bs, 0, bytes, count, len);

        this.count += bs.length;

        return this;
    }

    public BytesBuilder appendLE(byte[] bs) {
        return append(invert(bs));
    }

    public BytesBuilder append(String hex) {
        return append(ByteUtil.toByte(hex));
    }

    public BytesBuilder appendLE(String hex) {
        return appendLE(ByteUtil.toByte(hex));
    }

    public BytesBuilder append(String hex, int bs) {
        return append(ByteUtil.toByte(hex, bs));
    }

    public BytesBuilder appendLE(String hex, int bs) {
        return appendLE(ByteUtil.toByte(hex, bs));
    }

    public BytesBuilder append(int i, int bs) {
        return append(ByteUtil.toByte(i, bs));
    }

    public BytesBuilder appendLE(int i, int bs) {
        return appendLE(ByteUtil.toByte(i, bs));
    }

    public BytesBuilder append(byte b1) {
        return append(new byte[]{b1});
    }

    public BytesBuilder appendLE(byte b1) {
        return appendLE(new byte[]{b1});
    }

    public BytesBuilder append(byte b1, byte b2) {
        return append(new byte[]{b1, b2});
    }

    public BytesBuilder appendLE(byte b1, byte b2) {
        return appendLE(new byte[]{b1, b2});
    }

    public BytesBuilder append(byte b1, byte b2, byte b3) {
        return append(new byte[]{b1, b2, b3});
    }

    public BytesBuilder appendLE(byte b1, byte b2, byte b3) {
        return appendLE(new byte[]{b1, b2, b3});
    }

    public BytesBuilder append(byte b1, byte b2, byte b3, byte b4) {
        return append(new byte[]{b1, b2, b3, b4});
    }

    public BytesBuilder appendLE(byte b1, byte b2, byte b3, byte b4) {
        return appendLE(new byte[]{b1, b2, b3, b4});
    }

    public byte[] sub(int start) throws APIException {
        return sub(start, length());
    }

    public byte[] sub(int start, int end) throws APIException {
        return Arrays.copyOfRange(bytes, start, end);
    }

    public int length() {
        return count;
    }

    public byte[] toArray() throws APIException {
        return Arrays.copyOfRange(bytes, 0, count);
    }

    @Override
    public String toString() throws APIException {
        return ByteUtil.toHex(toArray());
    }

    /**
     * 数组扩容
     *
     * @param bytes    原数组
     * @param capacity 容量
     * @param len      希望扩大长度
     * @return 扩容后的数组
     */
    private static byte[] dil(byte[] bytes, int capacity, int len) {
        return Arrays.copyOf(bytes, bytes.length + capacity + len);
    }

    /**
     * 翻转数组内容
     *
     * @param bs 原数组
     * @return 翻转后的数组
     * @throws APIException 普通异常
     */
    private static byte[] invert(byte[] bs) throws APIException {
        if (bs == null || bs.length == 0) return bs;

        int length = bs.length;
        byte[] answer = new byte[length];
        for (int i = 0; i < answer.length; i++) {
            answer[i] = bs[length - i - 1];
        }

        return answer;
    }

}
